"""
爬虫失败记录模型
记录爬取过程中失败的数据，便于后续重试和分析
"""
from datetime import datetime
from typing import Optional, Dict, Any
from axiom_boot.database.base_model import BaseModel
from sqlalchemy import String, Integer, DateTime, Text, Enum, BigInteger
from sqlalchemy.orm import Mapped, mapped_column
from axiom_boot.core.types import BigInt


class ScraperFailedRecord(BaseModel):
    """爬虫失败记录模型"""
    
    __tablename__ = "scraper_failed_record"
    __allow_unmapped__ = True

    # 显式重写 id 以符合【主键覆盖原则】
    id: Mapped[BigInt] = mapped_column(BigInteger, primary_key=True, comment="主键ID (雪花ID)")
    
    # 基本信息
    site_name: Mapped[str] = mapped_column(String(50), nullable=False, comment="网站名称")
    failure_type: Mapped[str] = mapped_column(String(50), nullable=False, comment="失败类型 (page_extract, detail_extract, data_save, file_download)")
    failure_stage: Mapped[str] = mapped_column(String(50), nullable=False, comment="失败阶段 (list_page, detail_page, database, storage)")
    
    # 标识信息
    page_number: Mapped[int] = mapped_column(Integer, nullable=True, comment="页面编号 (如果是页面级失败)")
    item_reference: Mapped[str] = mapped_column(String(100), nullable=True, comment="数据项引用标识 (通用标识符)")
    target_url: Mapped[str] = mapped_column(Text, nullable=True, comment="失败的目标URL")
    
    # 失败详情
    error_message: Mapped[str] = mapped_column(Text, nullable=True, comment="错误信息")
    error_code: Mapped[str] = mapped_column(String(20), nullable=True, comment="错误代码")
    stack_trace: Mapped[str] = mapped_column(Text, nullable=True, comment="错误堆栈")
    
    # 重试信息
    retry_count: Mapped[int] = mapped_column(Integer, default=0, comment="重试次数")
    max_retry: Mapped[int] = mapped_column(Integer, default=3, comment="最大重试次数")
    retry_status: Mapped[str] = mapped_column(
        Enum('pending', 'retrying', 'success', 'failed', name='retry_status_enum'),
        default='pending',
        comment="重试状态 (pending, retrying, success, failed)"
    )
    last_retry_time: Mapped[datetime] = mapped_column(DateTime, nullable=True, comment="最后重试时间")
    
    # 上下文信息
    task_id: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, comment="关联的任务ID")
    worker_id: Mapped[Optional[str]] = mapped_column(String(50), nullable=True, comment="处理的Worker ID")
    failure_data: Mapped[Optional[str]] = mapped_column(Text, nullable=True, comment="失败时的数据快照JSON")


# 失败类型常量
class FailureType:
    """失败类型枚举"""
    PAGE_EXTRACT = "page_extract"  # 页面提取失败
    DETAIL_EXTRACT = "detail_extract"  # 详情提取失败
    DATA_SAVE = "data_save"  # 数据保存失败
    FILE_DOWNLOAD = "file_download"  # 文件下载失败


# 失败阶段常量
class FailureStage:
    """失败阶段枚举"""
    LIST_PAGE = "list_page"  # 列表页面
    DETAIL_PAGE = "detail_page"  # 详情页面
    DATABASE = "database"  # 数据库操作
    STORAGE = "storage"  # 存储操作


# 重试状态常量
class RetryStatus:
    """重试状态枚举"""
    PENDING = "pending"  # 等待重试
    RETRYING = "retrying"  # 重试中
    SUCCESS = "success"  # 重试成功
    FAILED = "failed"  # 重试失败
